package com.jiangyao.common.aop;

import com.jiangyao.common.annotation.Cache;
import com.jiangyao.common.constants.SystemConstants;
import com.jiangyao.common.utils.JsonUtil;
import com.jiangyao.common.utils.SpringBeanFactoryUtils;
import com.jiangyao.common.utils.StringUtils;
import com.jiangyao.component.RedisComponent;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.net.URLEncoder;

/**
 * 缓存aop
 *
 * @author: yangyongchuan
 * @create: 2020年06月06日 17:28
 */
@Aspect
public class CacheAop {

	private static RedisComponent redisComponent;

	private String prefix = "jiangyao_";

	static {
		redisComponent = SpringBeanFactoryUtils.getBean(RedisComponent.class);
	}

	public CacheAop() {
	}

	public CacheAop(String prefix) {
		this.prefix = prefix;
	}

	@Pointcut(value = "@annotation(cache)")
	public void pointcut(Cache cache) {
	}


	@Around(value = "pointcut(cache)", argNames = "pjp,cache")
	public Object doAround(ProceedingJoinPoint pjp, Cache cache) throws Throwable {
		if (redisComponent == null) {
			return pjp.proceed();
		}
		Method method = ((MethodSignature) pjp.getSignature()).getMethod();
//		Cache cache1 = method.getAnnotation(Cache.class);
//		if (cache1 == null) {
//			cache1 = method.getClass().getAnnotation(Cache.class);
//		}
//		if (cache1 == null) {
//			return pjp.proceed();
//		}
		//指定过期时间
		int expire = cache.expire();
		//开始生成key
		StringBuilder key = new StringBuilder();
		//处理类名和方法名
		key.append(method.getDeclaringClass().getSimpleName());
		key.append(".").append(method.getName());
		//处理参数
		Class[] names = method.getParameterTypes();
		Object[] values = pjp.getArgs();
		if (names.length > 0) {
			boolean isFirst = true;
			for (int i = 0; i < names.length; i++) {
				if (values[i] == null) {
					continue;
				}
				if (isFirst) {
					key.append("?").append(names[i].getSimpleName()).append("=").append(obj2str(values[i]));
					isFirst = false;
				} else {
					key.append("&").append(names[i]).append("=").append(obj2str(values[i]));
				}
			}
		}
		String cacheKey = prefix + key.toString();
		Object value = redisComponent.get(cacheKey);
		if (value != null) {
			return value;
		}
		value = pjp.proceed();
		if (value != null) {
			redisComponent.set(cacheKey, value, expire);
		}
		return value;
	}


	/**
	 * 对象转字符串
	 *
	 * @param obj
	 * @return 结果
	 */
	private String obj2str(Object obj) {
		if (obj instanceof HttpServletResponse) {
			return "";
		}
		if (obj instanceof HttpServletRequest) {
			HttpServletRequest request = (HttpServletRequest) obj;
			String token = request.getHeader(SystemConstants.LOGIN_TOKEN);
			if (StringUtils.isEmpty(token)) {
				token = request.getParameter(SystemConstants.LOGIN_TOKEN);
			}
			return token == null ? "" : token;
		}
		if (obj instanceof String || obj instanceof Boolean
				|| obj instanceof Integer || obj instanceof Float ||
				obj instanceof Double) {
			return obj.toString();
		}
		try {
			return URLEncoder.encode(JsonUtil.toJSONString(obj), "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
}
